﻿using Abp.Application.Services.Dto;
using Abp.AspNetCore.Mvc.Controllers;
using Batman.Identity;
using IdentityServer4.EntityFramework.Entities;
using IdentityServer4.EntityFramework.Interfaces;
using IdentityServer4.Stores;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using static IdentityModel.OidcConstants;

namespace IdentityServer4.Quickstart.UI
{
    public class ClientController : AbpController
    {
        private readonly IClientStore _clientStore;
        private readonly IConfigurationDbContext _context;

        public ClientController(IClientStore clientStore, IConfigurationDbContext context)
        {
            _clientStore = clientStore;
            _context = context;
        }

        public ActionResult List(PagedResultRequestDto page)
        {
            var query = _context.Clients.AsNoTracking();
            var clients = query.OrderBy(t => t.Id).Skip(page.SkipCount).Take(page.MaxResultCount).ToList();
            var total = query.Count();

            var model = new PagedResultDto<Client>(total, clients);
            return View(model);
        }

        [Authorize]
        [HttpGet]
        public ActionResult Create()
        {
            return View();
        }

        [Authorize]
        [HttpPost]
        public async Task<ActionResult> Create(CreateClientInput model)
        {
            if (!ModelState.IsValid) return View(model);

            var query = _context.Clients.AsNoTracking();

            if (query.Any(t => t.ClientName == model.ClientName))
            {
                ModelState.AddModelError(string.Empty, $"应用名称 '{model.ClientName}'已存在");
                return View(model);
            }
            if (query.Any(t => t.ClientId == model.ClientId))
            {
                ModelState.AddModelError(string.Empty, $"ClientId '{model.ClientId}'已存在");
                return View(model);
            }


            #region 组成client数据
            Client client = new Client();

            client.ClientId = model.ClientId;
            client.ClientName = model.ClientName;

            var clientGrantType = new ClientGrantType();
            clientGrantType.GrantType = GrantTypes.Implicit;
            clientGrantType.Client = client;

            client.AllowedGrantTypes = new List<ClientGrantType> { clientGrantType };

            var redirectUri = new ClientRedirectUri();
            redirectUri.Client = client;
            redirectUri.RedirectUri = model.RedirectUri;
            client.RedirectUris = new List<ClientRedirectUri> { redirectUri };

            var postLogoutRedirectUris = new ClientPostLogoutRedirectUri();
            postLogoutRedirectUris.Client = client;
            postLogoutRedirectUris.PostLogoutRedirectUri = model.PostLogoutRequrectUri;
            client.PostLogoutRedirectUris = new List<ClientPostLogoutRedirectUri> { postLogoutRedirectUris };

            client.AllowedScopes = new List<ClientScope>
            {
                new ClientScope{ Client = client, Scope = IdentityServerConstants.StandardScopes.OpenId},
                new ClientScope{ Client = client, Scope = IdentityServerConstants.StandardScopes.Profile}
            };

            var secret = new ClientSecret();
            secret.Client = client;

            secret.Value = model.Secret;
            client.ClientSecrets = new List<ClientSecret> { secret };

            client.Enabled = model.Enabled;
            client.Description = model.Secret;

            #endregion

            _context.Clients.Add(client);

            await _context.SaveChangesAsync();

            return Content("新建应用成功");
        }

        [Authorize]
        [HttpGet]
        public ActionResult Update(int id)
        {
            var record = _context.Clients.AsNoTracking()
                                         .Include(t => t.PostLogoutRedirectUris)
                                         .Include(t => t.RedirectUris)
                                         .Include(t => t.ClientSecrets)
                                         .Include(t => t.AllowedScopes)
                                         .Where(t => t.Id == id)
                                         .FirstOrDefault();

            var model = new UpdateClientInput
            {
                ClientId = record.ClientId,
                Id = record.Id,
                ClientName = record.ClientName,
                Description = record.Description,
                Enabled = record.Enabled,
                PostLogoutRequrectUri = record.PostLogoutRedirectUris.FirstOrDefault()?.PostLogoutRedirectUri,
                RedirectUri = record.RedirectUris.FirstOrDefault()?.RedirectUri,
                Secret = record.ClientSecrets.FirstOrDefault()?.Value,
                AllowedScopes = record.AllowedScopes
            };

            return View(model);
        }

        [Authorize]
        [HttpPost]
        public async Task<ActionResult> Update(UpdateClientInput model)
        {
            if (!ModelState.IsValid) return View(model);

            var client = _context.Clients.Include(t => t.PostLogoutRedirectUris)
                                 .Include(t => t.RedirectUris)
                                 .FirstOrDefault(t => t.Id == model.Id);
            if (client == null)
            {
                ModelState.AddModelError(string.Empty, "应用不存在");
                return View(model);
            }

            var query = _context.Clients.AsNoTracking();

            if (query.Any(t => t.ClientName == model.ClientName && t.Id != model.Id))
            {
                ModelState.AddModelError(string.Empty, $"应用名称 '{model.ClientName}'已存在");
                return View(model);
            }
            if (query.Any(t => t.ClientId == model.ClientId && t.Id != model.Id))
            {
                ModelState.AddModelError(string.Empty, $"ClientId '{model.ClientId}'已存在");
                return View(model);
            }

            client.ClientName = model.ClientName;
            client.Description = model.Description;
            client.Enabled = model.Enabled;
            client.ClientId = model.ClientId;

            if (model.RedirectUri != client.RedirectUris.First().RedirectUri)
            {
                var redirectUri = new ClientRedirectUri();
                redirectUri.Client = client;
                redirectUri.RedirectUri = model.RedirectUri;
                client.RedirectUris.Clear();
                client.RedirectUris = new List<ClientRedirectUri> { redirectUri };
            }
            if (model.PostLogoutRequrectUri != client.PostLogoutRedirectUris.First().PostLogoutRedirectUri)
            {
                var postLogoutRedirectUris = new ClientPostLogoutRedirectUri();
                postLogoutRedirectUris.Client = client;
                postLogoutRedirectUris.PostLogoutRedirectUri = model.PostLogoutRequrectUri;

                client.PostLogoutRedirectUris.Clear();
                client.PostLogoutRedirectUris = new List<ClientPostLogoutRedirectUri> { postLogoutRedirectUris };
            }


            await _context.SaveChangesAsync();

            return Content("编辑应用成功");
        }
    }
}
